#include "sprite.h"
#ifdef DEBUG
#include <stdio.h>
#endif

int r8b_drawUpdateSprite(R8B_Sprite *sprite, Uint32 now, SDL_Surface *dst) {
  if(sprite->x != sprite->to_x && sprite->y != sprite->to_y) {
    double tick_tack = now - sprite->last_tick;
    sprite->x += sprite->delta_x * tick_tack;
    sprite->y += sprite->delta_y * tick_tack;

    if((sprite->delta_x > 0 && sprite->x > sprite->to_x) || (sprite->delta_x < 0 && sprite->x < sprite->to_x)) {
      sprite->x = sprite->to_x;
      sprite->delta_x = 0;
    }
    if((sprite->delta_y > 0 && sprite->y > sprite->to_y) || (sprite->delta_y < 0 && sprite->y < sprite->to_y)) {
      sprite->y = sprite->to_y;
      sprite->delta_y = 0;
    }
  }
  SDL_Rect r = { sprite->x, sprite->y, 0, 0 };
  sprite->last_tick = now;
  return r8b_drawSprite(sprite, now, dst, &r);
}

int r8b_drawSprite(R8B_Sprite *sprite, Uint32 now, SDL_Surface *dst, SDL_Rect *dstpos) {
  SDL_Surface *source;

  source = r8b_getCurrentSpriteSurface(sprite, now);
  return SDL_BlitSurface(source, NULL, dst, dstpos);
}

SDL_Surface *r8b_getCurrentSpriteSurface(R8B_Sprite *sprite, Uint32 now) {
#ifdef DEBUG
  printf
    ("sprite=%p start=$%08X now=$%08X start-now=$%08x divisor=$%04hx frame=$%04hx\n",
     sprite, sprite->start_tick, now, (now - sprite->start_tick),
     sprite->speed_divisor,
     ((now -
       sprite->start_tick) / sprite->speed_divisor) % sprite->surface_count);
#endif
  return sprite->
    surface_ptr[((now -
		  sprite->start_tick) / sprite->speed_divisor) %
		sprite->surface_count];
}

void r8b_init_sprite(R8B_Sprite *sprite, Uint32 now,
		     SDL_Surface **surfaces,
		     Uint16 surface_count, Uint16 delay) {
  sprite->start_tick = now;
  sprite->surface_ptr = surfaces;
  sprite->surface_count = surface_count;
  sprite->flags = 0;
  sprite->speed_divisor = delay;
  sprite->to_x = 0;
  sprite->to_y = 0;
  sprite->x = 0;
  sprite->y = 0;
}

R8B_Sprite *r8b_createSprite(Uint32 now,
			     SDL_Surface **surfaces,
			     Uint16 surface_count, Uint16 delay) {
  R8B_Sprite *ptr = malloc(sizeof(R8B_Sprite));

  if(ptr != NULL) {
    r8b_init_sprite(ptr, now, surfaces, surface_count, delay);
  }
  return ptr;
}

void r8b_destroySprite(R8B_Sprite *sprite) {
  Uint32 i;

  if(sprite == NULL) return;
  if((sprite->flags & R8B_SPRITE_FLAG_OWN_SURFACES) != 0) {
    for(i = 0; i < sprite->surface_count; ++i) {
      SDL_FreeSurface(sprite->surface_ptr[i]);
    }
  }
  free(sprite);
}

double r8b_moveSpriteTo(R8B_Sprite *sprite, Sint16 x, Sint16 y, double speed) {
  double dx = x - sprite->x;
  double dy = y - sprite->y;
  double d = sqrt(dx*dx + dy*dy);

  sprite->delta_x = dx * speed / d;
  sprite->delta_y = dy * speed / d;
  sprite->to_x = x;
  sprite->to_y = y;
  sprite->last_tick = SDL_GetTicks();
  return d;
}

void r8b_warpSprite(R8B_Sprite *sprite, Sint16 x, Sint16 y) {
  sprite->x = x;
  sprite->y = y;
}
